from logging import getLogger
from typing import BinaryIO, Optional, Union
import oss2
from oss2.models import GetObjectResult
from fastapi import UploadFile
from app.core.storage.base import BaseStorage

logger = getLogger(__name__)


class OSSStorage(BaseStorage):
    """阿里云OSS存储实现"""

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # 创建OSS认证对象
        self.auth = oss2.Auth(self.access_key, self.secret_key)
        # 创建Bucket对象
        self.bucket = oss2.Bucket(self.auth, self.endpoint, self.bucket)

    async def save(self, file: Union[BinaryIO, UploadFile], filename: str) -> str:
        """保存文件到OSS"""
        try:
            # 生成存储路径
            storage_path = self.generate_storage_path(filename)

            # 上传文件
            if isinstance(file, UploadFile):
                content = await file.read()
                self.bucket.put_object(storage_path, content, headers={"Content-Type": self.get_content_type(filename)})
            else:
                self.bucket.put_object(storage_path, file, headers={"Content-Type": self.get_content_type(filename)})

            return storage_path

        except Exception as e:
            logger.error(f"OSS上传失败: {str(e)}")
            raise Exception("文件上传失败")

    async def delete(self, file_path: str) -> bool:
        """从OSS删除文件"""
        try:
            self.bucket.delete_object(file_path)
            return True
        except Exception as e:
            logger.error(f"OSS删除失败: {str(e)}")
            return False

    async def get(self, file_path: str) -> Optional[BinaryIO]:
        """从OSS获取文件"""
        try:
            obj: GetObjectResult = self.bucket.get_object(file_path)
            return obj
        except Exception as e:
            logger.error(f"OSS获取文件失败: {str(e)}")
            return None

    async def get_url(self, file_path: str, expires_in: int = 3600) -> str:
        """获取OSS文件URL"""
        try:
            if self.base_url:
                return f"{self.base_url}/{file_path}"

            # 生成签名URL
            url = self.bucket.sign_url("GET", file_path, expires_in)
            return url
        except Exception as e:
            logger.error(f"生成URL失败: {str(e)}")
            raise Exception("生成文件访问URL失败")
